AE = typeof AE !== 'undefined' ? AE : {};
AE.PrefsHelper = (function() {
    var Helper = AE.Helper;

    var Constants = {
        NO_SUCH_PREF : "No preference named '{key}'"
    };

    var DefaultPrefHandler = {
        "key" : "",

        "cache" : undefined,

        "default" : undefined,

        get : function() {
            var val = this.cache;
            if (val === undefined) {
                val = this.cache = this.load();
            }

            return val;
        },

        set : function(val) {
            this.save(val);
            this.cache = undefined;
        },

        save : function(val) {
            PrefsHelper.setLocal(this.key, val);
        },

        load : function() {
            var val = PrefsHelper.getLocal(this.key);
            if (val === undefined) {
                val = this['default'];
            }

            return val;
        },

        renderUI : function(doc) {
        },

        saveFromUI : function(doc) {
        }
    };

    var PrefsHelper = {
        getLocal : function(key) {
            return (key in localStorage ? localStorage[key] : null);
        },

        setLocal : function(key, val) {
            localStorage[key] = val;
        },

        add : function(pref) {
            if (pref && pref.key) {
                pref = Helper.mergeObject(DefaultPrefHandler, pref);
                this.prefs.push(pref);
                this.prefs[pref.key] = pref;
            }
        },

        getAll : function(obj) {
            obj = obj || {};
            this.prefs.forEach(function(pref) {
                pref.get(obj);
            });

            return obj;
        },

        get : function(key) {
            var pref = this.prefs[key];
            if (pref) {
                return pref.get();
            }

            throw new Error(Helper.format(Constants.NO_SUCH_PREF, { key : key }));
        },

        set : function(key, val) {
            var pref = this.prefs[key];
            if (pref) {
                pref.set(val);
            }
        },

        load : function(key) {
            var pref = this.prefs[key];
            if (pref) {
                return pref.load(val);
            }

            throw new Error(Helper.format(Constants.NO_SUCH_PREF, { key : key }));
        },

        renderUI : function(doc) {
            this.prefs.forEach(function(pref) {
                pref.renderUI(doc.getElementById("pref_" + pref.key));
            });
        },

        saveFromUI : function(doc) {
            this.prefs.forEach(function(pref) {
                pref.saveFromUI(doc.getElementById("pref_" + pref.key));
            });
        },

        prefs : []
    };

    /**
     * shorterners points out which short urls will be auto expanded
     * @type        Array<String>
     * @default     bit.ly
     */
    PrefsHelper.add({
        "key" : "shorterners",
        "default" : "bit.ly",
        get : function() {
            var str = DefaultPrefHandler.get.call(this);
            return str.replace(/\r/g, "").split("\n");
        },

        renderUI : function(el) {
            el.value = this.get().join("\n");
        },

        saveFromUI : function(el) {
            this.set(el.value);
        }
    });

    /**
     * Preference expander point using which expander to auto expand the short url
     * @type        String
     * @default     untr.im
     */
    PrefsHelper.add({
        "key" : "expander",
        "default" : "untr.im",
        renderUI : function(el) {
            el.options.length = 0;

            var curExpander = this.get(),
                expanders = AE.Expanders.getExpanders(),
                index = 0;

            expanders.forEach(function(str) {
                el.options.add(new Option(str, str));
                if (curExpander === str) {
                    el.selectedIndex = index;
                }
                index++
            });
        },
        saveFromUI : function(el) {
            this.set(el.options[el.selectedIndex].value);
        }
    });

    return PrefsHelper;
})();